package com.secsbrain.development.web.ws.handle;

import com.alibaba.fastjson.JSON;
import com.secsbrain.common.ResponseVo;
import com.secsbrain.common.utils.RedisUtil;
import com.secsbrain.deploy.client.constant.EnumDefinition.BuildStatus;
import com.secsbrain.deploy.client.iface.DeployService;
import com.secsbrain.deploy.client.model.BuildLog;
import com.secsbrain.deploy.client.model.BuildRecord;
import com.secsbrain.development.web.ws.base.BaseHandler;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class LogSubscriptionHandler extends BaseHandler {
    @Autowired
    private DeployService deployService;
    
    private static final String BLANK = "";
    
    private static final String WAIT = "正在努力执行中，已执行";
    
    private Map<Long, Long> snapshotIdLengthMap=new ConcurrentHashMap<Long, Long>();

    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) {
        String strId = String.valueOf(message.getPayload());
        try {
        	String[] paramArry=strId.split(",");
            Long snapshotId = Long.valueOf(paramArry[0]);
            String envName=paramArry[1];

            ResponseVo<BuildRecord> buildRecordVo = deployService.queryBuildRecordByBuildId(snapshotId, envName);
            if(!buildRecordVo.isSuccess()){
            	LOGGER.error("查询构建记录失败："+buildRecordVo.getMsg());
             	return;
            }
            BuildRecord snapshot=buildRecordVo.getData();
            if (snapshot != null) {
            	LOGGER.info("[LogSubscriptionHandler.handleTextMessage]读取日志记录:snapshotId:[{}]", snapshot.getBuildId());
                this.send(session, "[INFO]\t开始读取日志...");
                this.send(session, "[INFO]\tLOG BEGIN [" + snapshot.getAppName() + "]");
            	readLog(snapshot, session,envName);
            }
        } catch (NumberFormatException e) {
            LOGGER.error("[LogSubscriptionHandler.handleTextMessage]不合法的snapshotId:[{}]", strId);
        }
    }

    private void readLog(BuildRecord snapshot, WebSocketSession session,String envName) {
        if (!session.isOpen()) {
            return;
        }
        Map<String, Object> params=new HashMap<String, Object>();
        params.put("appName", snapshot.getAppName());
        params.put("branch", snapshot.getBranch());
        params.put("hostNames", snapshot.getHostNames());
        params.put("deployingTask", true);
        
        ResponseVo<BuildLog> logVo=deployService.getBuildLog(snapshot.getBuildId(), snapshotIdLengthMap.get(snapshot.getBuildId()),envName);
        if (logVo.getData() != null && logVo.getData().getLogContent() != null ) {
            String line = logVo.getData().getLogContent();
            if("true".equals(logVo.getData().getxMoreData())){
            	snapshotIdLengthMap.put(snapshot.getBuildId(), Long.parseLong(logVo.getData().getxTextSize()));
                this.send(session, "".equals(line) ? BLANK : line);
                this.send(session, JSON.toJSONString(params));
            }else{
            	if(!line.contains("Started by user")&&
            		Long.parseLong(logVo.getData().getxTextSize())>snapshotIdLengthMap.get(snapshot.getBuildId())){
            		snapshotIdLengthMap.put(snapshot.getBuildId(), Long.parseLong(logVo.getData().getxTextSize()));
                    this.send(session, "".equals(line) ? BLANK : line);
                    this.send(session, JSON.toJSONString(params));
            	}
            }
        }else{
        	String redisKey="LOG_SUBSCRIPTION_USE"+snapshot.getBuildId();
    		if(RedisUtil.kExists(redisKey)){
    			int count=Integer.parseInt(RedisUtil.get(redisKey))+1;
    			RedisUtil.put(redisKey, count+"", 60*30);
          	}else{
            	RedisUtil.put(redisKey, "0", 60*30);
         	}
             
    		int waitSecond=Integer.parseInt(RedisUtil.get(redisKey));
    		if(waitSecond>=5){
                this.send(session, WAIT+RedisUtil.get("LOG_SUBSCRIPTION_"+snapshot.getBuildId())+"秒" );
                RedisUtil.remove(redisKey);
    		}
        }
    }

    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        super.afterConnectionEstablished(session);
        String query = session.getUri().getQuery();
        Long id = null;
        String params=null;
        try {
            if (query != null) {
                String[] split = StringUtils.split(query, '&');
                for (String s : split) {
                    if (s.contains("snapshotId")) {
                    	params=StringUtils.split(s, "=")[1];
                    	String[] paramArry=params.split(",");
                    	id=Long.valueOf(paramArry[0]);
                        onSubscription(id, session,paramArry[1]);
                        break;
                    } else if (s.contains("projectId")) {
//                        id = Long.valueOf(StringUtils.split(s, "=")[1]);
//                        BuildSnapshot snapshot = buildSnapshotComponent.findProcessingByProjectId(id);
//                        if (snapshot != null) {
//                            onSubscription(snapshot.getId(), session);
//                            return;
//                        }
                        this.send(session, "似乎已经没有正在执行的任务了");
                        this.send(session, "可能是这个任务已经飞速的执行完成了,去历史记录里看看吧...");
                        this.send(session, "[INFO]\tLOG FINISHED [projcetId:" + id + "]");
                        try {
                            session.close();
                        } catch (IOException ex) {
                            LOGGER.info("[LogSubscriptionHandler.afterConnectionEstablished]关闭socket,session id:[{}]", session.getId());
                        }
                        break;
                    }
                }
            }
        } catch (NumberFormatException e) {
            LOGGER.error("[LogSubscriptionHandler.afterConnectionEstablished]不合法的ID:[{}]", id);
            this.send(session, "不合法的ID:" + id);
            try {
                session.close();
            } catch (IOException ex) {
                LOGGER.info("[LogSubscriptionHandler.afterConnectionEstablished]关闭socket,session id:[{}]", session.getId());
            }
        }

    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        LOGGER.debug("WebSocketSession连接关闭，sessionId:[{}]", session.getId());
    }

    @Override
    public String[] getPaths() {
        return new String[]{"/subscription"};
    }

    private void onSubscription(long snapshotId, WebSocketSession webSocketSession,String envName) {
        try {
            ResponseVo<BuildRecord> buildRecordVo = deployService.queryBuildRecordByBuildId(snapshotId,envName);
            if(!buildRecordVo.isSuccess()){
            	LOGGER.error("查询构建记录失败："+buildRecordVo.getMsg());
            	return;
            }
            BuildRecord buildRecord=buildRecordVo.getData();
            
            LOGGER.info("[LogSubscriptionHandler.onSubscription]读取日志记录:snapshotId:[{}]", buildRecord.getBuildId());
            this.send(webSocketSession, "[INFO]\t开始读取日志...");
            this.send(webSocketSession, "[INFO]\tLOG BEGIN [" + buildRecord.getAppName() + "]");
        	snapshotIdLengthMap.put(snapshotId, 0L);

        	int count = 0;
        	int waitCount = 0;
        	
            String logRedisKey="LOG_SUBSCRIPTION_"+snapshotId;
            
            while ( BuildStatus.ING.getCode().equals(buildRecord.getStatus())|| BuildStatus.WAIT.getCode().equals(buildRecord.getStatus())) {
            	ResponseVo<BuildRecord> snapshotVo = deployService.queryBuildRecordByBuildId(snapshotId,envName);
                if(!snapshotVo.isSuccess()){
                	LOGGER.error("查询构建记录失败："+snapshotVo.getMsg());
                    continue;
                }
                
                if(RedisUtil.kExists(logRedisKey)){
                	int time=Integer.parseInt(RedisUtil.get(logRedisKey))+1;
                    RedisUtil.put(logRedisKey, time+"", 60*30);
                }else{
                    RedisUtil.put(logRedisKey, "0", 60*30);
                }
                
                BuildRecord snapshot=snapshotVo.getData();
                LOGGER.debug("构建ID："+snapshot.getBuildId()+"，构建状态："+snapshot.getStatus());
                if(BuildStatus.WAIT.getCode().equals(snapshot.getStatus())){
                	try {
	                	if (waitCount++ > 30) {
	                        this.send(webSocketSession, "发布任务排队中，请返回发布记录查看");
	                        this.send(webSocketSession, "[INFO]\tLOG FINISHED [groupId:" + snapshotId + "]");
	                        this.send(webSocketSession,JSON.toJSONString(snapshot));
	                        return;
	                    }
                        Thread.sleep(1000);
                	} catch (InterruptedException ignored) {
                    }
                }else if ( BuildStatus.ING.getCode().equals(snapshot.getStatus())) {
                    readLog(snapshot, webSocketSession,envName);
                    try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
					}
                } else {
                    try {
                        if (count++ > 5) {
                            this.send(webSocketSession, "似乎已经没有正在执行的任务了");
                            this.send(webSocketSession, "[INFO]\tLOG FINISHED [groupId:" + snapshotId + "]");
                            this.send(webSocketSession,JSON.toJSONString(snapshot));
                            
                            snapshotIdLengthMap.remove(snapshot.getBuildId());
                            
                            RedisUtil.remove(logRedisKey);
                            RedisUtil.remove("LOG_SUBSCRIPTION_USE"+snapshot.getBuildId());
                            return;
                        }
                        
                        readLog(snapshot, webSocketSession,envName);
                        Thread.sleep(1000);
                    } catch (InterruptedException ignored) {
                    }
                }
            }
        } finally {
            try {
                webSocketSession.close();
            } catch (IOException ex) {
                LOGGER.info("[LogSubscriptionHandler.afterConnectionEstablished]关闭socket异常,session id:[{}]", webSocketSession.getId(), ex);
            }
        }
    }

    public void send(WebSocketSession session, String message) {
        try {
            if (session.isOpen()) {
                session.sendMessage(new TextMessage(message + System.lineSeparator()));
            }
        } catch (IOException e) {
            LOGGER.error("发送WebSocket消息出现异常...", e);
        }
    }

}
